package kibahed.uni.charts;

import ij.measure.CurveFitter;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

import java.awt.Shape;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.util.ShapeUtilities;



@XmlRootElement
public class SimpleChart extends AKChart {

	protected int count = 0;
	protected List<String> info = new ArrayList<String>();
	protected String algorithm = "";
	protected String tspFile = "";
	protected Integer chartType;

	protected Integer drawingMode = AKChart.reportStyle; 

	@XmlTransient
	protected XYDataPairList activeDataList;
	@XmlTransient
	protected XYDataPairList data;

//	public SimpleChart(){
//		createColors();
//		drawingMode = AKChart.onlyFittedValues;
//	}
	
	public SimpleChart(Integer style) {
		data = new XYDataPairList();
		activeDataList = data;
		dataPairLists.add(data);
		createColors();
		createShapes();
		drawingMode = style;
	}
	
	public SimpleChart() {
		
		
		
	}

	protected void createColors() {
		colors = new LinkedList<Color>();
		colors.add(Color.RED);
		colors.add(Color.BLUE);
		colors.add(Color.ORANGE);
		colors.add(Color.CYAN);
		colors.add(Color.DARK_GRAY);
		colors.add(Color.YELLOW);
		colors.add(Color.MAGENTA);
		colors.add(Color.BLACK);
		colors.add(Color.LIGHT_GRAY);
		colors.add(Color.PINK);
		colors.add(Color.GREEN);

	}
	
	protected void createShapes() {
		shapes = new LinkedList<Shape>();
		Shape a = ShapeUtilities.createDiagonalCross(6, 1);
		Shape b = ShapeUtilities.createDownTriangle(6);
		Shape c = ShapeUtilities.createDiamond(6);
		Shape d = ShapeUtilities.createUpTriangle(6);
		Shape e = ShapeUtilities.createUpTriangle(6);
		shapes.add(a);
		shapes.add(b);
		shapes.add(c);
		shapes.add(d);
		shapes.add(e);
	}

	@Override
	public void setInfo(List<String> infos) {
		tspFile = infos.get(0);
		algorithm = infos.get(1);
		System.out.println("Info Setted" + tspFile + algorithm);

	}

	@Override
	public List<String> getInfos() {
		
		return null;
	}

	public void addXYDataPair(XYDataPair pair) {
		activeDataList.addXYDataPair(pair);
		count++;
	}
	
	@Override
	public void addData(List<Object> data) {

		double avgPathLength = (double) data.get(0);
		XYDataPair pair = new XYDataPair();
		pair.setxValue(count);
		pair.setyValue(avgPathLength);
		activeDataList.addXYDataPair(pair);

		count++;

	}

	@Override
	public List<Integer> getData() {
		
		return null;
	}

	@Override
	public void generateChart(Integer view) {

		
		JFrame frame = new JFrame();
		frame.setSize(800, 800);
		frame.setVisible(true);
		// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		JPanel testPanel = new JPanel();
		testPanel.setSize(100, 100);
		testPanel.setLayout(new GridLayout());
		testPanel.setVisible(true);

		frame.add(testPanel);

		XYSeriesCollection dataset = new XYSeriesCollection();

		for (int i = 0; i < dataPairLists.size(); i++) {

			
			XYSeries series1 = new XYSeries(getValueNames()[0]+i);
			XYSeries series2 = new XYSeries(getFittedValueNames()[0]+i);

			double[] xDoubleValues = dataPairLists.get(i).getXValues();

			double[] yDoubleValues = dataPairLists.get(i).getYValues();

			for (int j = 0; j < xDoubleValues.length; j++) {
				series1.add(xDoubleValues[j], yDoubleValues[j]);
			}
			
			
			CurveFitter cf = new CurveFitter(xDoubleValues, yDoubleValues);
			cf.doFit(CurveFitter.POLY5);

			for (int m = cf.getXPoints().length - 1; m >= 0; m--) {
				double fittedValue = cf.f(cf.getParams(), xDoubleValues[m]);

				series2.add(xDoubleValues[m], fittedValue);
			}
			
			if(drawingMode == AKChart.fittedValuesAndDataPoints) {
				dataset.addSeries(series1);
				dataset.addSeries(series2);
			}
			
			if(drawingMode == AKChart.onlyFittedValues) {
				dataset.addSeries(series2);
			}
			
			if(drawingMode == AKChart.onlyDataPoints) {
				dataset.addSeries(series1);
			}
			
		}

		chart = ChartFactory.createXYLineChart("", xAxisName, yAxisName,
				dataset, PlotOrientation.VERTICAL, true, false, false);
		XYPlot plot = chart.getXYPlot();
		plot.setBackgroundPaint(Color.WHITE);
		plot.setDomainGridlinePaint(Color.GRAY);
		plot.setRangeGridlinePaint(Color.GRAY);

		

		XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer() {
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			@Override
			protected boolean isLinePass(int pass) {
				return pass == 1;
			}

			@Override
			protected boolean isItemPass(int pass) {
				return pass == 0;
			}
		};

		plot.setRenderer(renderer);

		XYItemRenderer itemRenderer = plot.getRenderer();
		BasicStroke stroke = new BasicStroke(3);
		
		BasicStroke s = new BasicStroke(10, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
		
		for (int i = 0; i < dataset.getSeriesCount(); i++) {
			int c = i;
			
			if (drawingMode == AKChart.fittedValuesAndDataPoints) {
				c = i/2;
				if (i % 2 == 0) {
					renderer.setSeriesLinesVisible(i, false);
					
					renderer.setSeriesShapesFilled(i, true);
					itemRenderer.setSeriesPaint(i, colors.get(c));
				} else {
					renderer.setSeriesShapesVisible(i, false);
					itemRenderer.setSeriesStroke(i, s);
					itemRenderer.setSeriesPaint(i, colors.get(c));
				}
			} else if(drawingMode == AKChart.onlyFittedValues) {
				
					renderer.setSeriesShapesVisible(i, false);
					itemRenderer.setSeriesStroke(i, s);
					itemRenderer.setSeriesPaint(i, colors.get(c));
				
			} else if(drawingMode == AKChart.onlyDataPoints) {
				
					renderer.setSeriesLinesVisible(i, false);
					renderer.setSeriesShapesFilled(i, true);
					itemRenderer.setSeriesPaint(i, colors.get(c));
				
			}
		}

		
		TextTitle t = chart.getTitle();
		t.setFont(getTitleFont());
		
		ValueAxis xAxis = chart.getXYPlot().getDomainAxis();
		ValueAxis yAxis = chart.getXYPlot().getRangeAxis();
		
		xAxis.setTickLabelFont(getxAxisValueFont());
		yAxis.setTickLabelFont(getyAxisValueFont());
		
		xAxis.setLabelFont(getxAxisLabelFont());
		yAxis.setLabelFont(getyAxisLabelFont());
		
		LegendTitle legendTitle = chart.getLegend();
		legendTitle.setItemFont(getLegendFont());
		
		xAxis.setLabelPaint(Color.BLACK);
		xAxis.setTickLabelPaint(Color.BLACK);
		yAxis.setLabelPaint(Color.BLACK);
		yAxis.setTickLabelPaint(Color.BLACK);
		legendTitle.setItemPaint(Color.BLACK);

		
		ChartPanel myChart = new ChartPanel(chart);
		
	
		
		testPanel.add(myChart);
		testPanel.validate();

	}

	@Override
	public void setChartType(Integer chartType) {
		this.chartType = chartType;
	}

	@Override
	public Integer getChartType() {
		return chartType;
	}

	public void setData(List<List<int[]>> tours) {

	}

	public String getAlgorithm() {
		return algorithm;
	}

	public void setAlgorithm(String algorithm) {
		this.algorithm = algorithm;
	}

	public String getxAxisName() {
		return xAxisName;
	}

	public void setxAxisName(String xAxisName) {
		this.xAxisName = xAxisName;
	}

	public String getyAxisName() {
		return yAxisName;
	}

	public void setyAxisName(String yAxisName) {
		this.yAxisName = yAxisName;
	}

	@Override
	public void startNewXYDataPairList() {
		XYDataPairList newData = new XYDataPairList();
		activeDataList = newData;
		dataPairLists.add(newData);
		count = 0;
		System.out.println("Amout of XY Data pair sets = "+dataPairLists.size());
	}

	@Override
	public void setDrawingMode(Integer drawingMode) {
		this.drawingMode = drawingMode;
	}

	@Override
	public Integer getDrawingMode() {
		return drawingMode;
	}

	@Override
	public void valdidatePanel() {
		// TODO Auto-generated method stub
		
	}
	
	protected void resetDrawingModeAfterLoading() {
		if(drawingMode == 200)
			drawingMode = AKChart.onlyFittedValues;
		if(drawingMode == 210) 
			drawingMode = AKChart.onlyDataPoints;
		if(drawingMode == 230) 
			drawingMode = AKChart.fittedValuesAndDataPoints;
		if(drawingMode == 240)
			drawingMode = AKChart.reportStyle;
		if(drawingMode == 250) 
			drawingMode = AKChart.trueLinePlusPoints;
			
	}
}
